package org.lexicon.ontologydocumentor

import java.util.List;
import com.hp.hpl.jena.ontology.*;
import com.hp.hpl.jena.rdf.model.*;

class OntologyDocumentWriter {
	
	OntologyDocument od;
	
	public OntologyDocumentWriter(OntologyDocument od) {
		this.od = od;
	}
	
	public String getContents() {
		String rt = this.getDocType();
		rt += this.getHeader();
		rt += this.getStartBody();
		rt += this.getVisibleHeader();
		rt += this.getHistory();
		rt += this.getToc();
		rt += this.getIntroduction();
		rt += this.getAbout();
		rt += this.getAcknowledgements();
		rt += this.getReferences();
		rt += this.getContactInformation();
		rt += this.getExamples();
		rt += this.getOverview();
		rt += this.getOntClasses();
		rt += this.getObjectProperties();
		rt += this.getDatatypeProperties();
		rt += this.getIndividuals();
		rt += this.getFooter();
		return rt.replaceAll("@en", "");
	}
	
	public String getDocType() {
		String docType = """
		<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd"> 
		<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" 
		"""
		this.od.getModel().getNsPrefixMap().each {
			docType += "xmlns:${it.key}=\"${it.value}\" \n";
		}	
		
		docType += ">\n";
		return docType;
	}
	
	public String getHeader() {
		String header = """
		<head> 
		  <title>${this.od.getTitle()}</title> 
		  <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> 
		  <link href="http://xmlns.com/xmlns-style.css" rel="stylesheet"  type="text/css" /> 
		  <link href="http://xmlns.com/foaf/spec/style.css" rel="stylesheet"  type="text/css" /> 
		  <link href="http://purl.org/innovation/ns.owl" rel="alternate"  type="application/rdf+xml" /> 
		</head>\n
		"""
		return header;
	}
	
	public String getStartBody() {
		return "<body>\n";
	}
	
	public String getVisibleHeader() {
		return """
		<h1>${this.od.getTitle()}</h1> 
		<h2>Document Namespace: <a href="${this.od.getUri()}">${this.od.getUri()}</a></h2>
		"""
	}
	
	public String getHistory() {
		String history =  """
		<dl> 
			<dt>Last Updated:</dt> 
		    <dd>${this.od.getLastUpdated()}</dd>
		    <dt>Latest version:</dt> 
		    <dd>${this.od.getThisVersion()}: <a href="${this.od.getUri()}">${this.od.getUri()}</a></dd> 
		    <dt>Authors:</dt> 
		    <dd>
		"""
		
		this.od.getAuthors().each { 
			history += """
				${it.toString()}	
			"""
		}
		
		history += """
		    </dd> 
		    <dt>Contributors:</dt> 
		    <dd>
		"""
		
		this.od.getContributors().each {
			history +=
		"""
		   ${it.toString()}
		"""
		}
		
		history += """  
		    </dd> 
		  </dl> 
		  ${this.getLicenceInformation()}	
		"""
		return history;
	}
	
	public String getLicenceInformation() {
		return """  
		  <!-- Creative Commons License --> 
		   <p><a href="http://creativecommons.org/licenses/by/1.0/">This work is licensed under a <a href="${this.od.getLicense()}">Creative Commons Attribution License</a>. This copyright applies to the <em>${this.od.getTitle()}</em> and accompanying documentation in RDF. Regarding underlying technology, this ontology uses W3C's <a href="http://www.w3.org/RDF/">RDF</a> technology, an open Web standard that can be freely used by anyone.</p> 		
		"""
	}
	
	public String getToc() {
		return """
		<h2 id="sec-toc">Table of Contents</h2> 
		  <ul> 
		    <li><a href="#sec-intro">Introduction</a></li> 
		    <li><a href="#sec-about">About this Ontology</a></li> 
		    <li><a href="#sec-overview">Overview</a></li> 
		    <li><a href="#sec-examples">Examples</a></li> 
		    <li><a href="#sec-classes">Classes</a></li> 
		    <li><a href="#sec-objectproperties">Object Properties</a></li> 
		    <li><a href="#sec-datatypeproperties">Datatype Properties</a></li> 
		    <li><a href="#sec-individuals">Individuals</a></li> 
		    <li><a href="#sec-contactinformation">Contact Information</a></li> 
		    <li><a href="#sec-licenseinformation">License Information</a></li> 
		    <li><a href="#sec-acknowledgements">Acknowledgements</a></li> 
		    <li><a href="#sec-references">References</a></li> 
		  </ul> 
		""" 
	}
	
	public String getIntroduction() {
		return """
		<a id="sec-intro"></a>
		<h2 id="intro">Introduction</h2>
		<p>Introduction to the ontology.</p>
		"""
	}
	
	public String getAbout() {
		return """
		<a id="sec-about"></a>
		<h2 id="about">About this Ontology</h2>
		<p>${this.od.getDescription()}</p>
		"""
	}
	
	public String getOverview() {
		String overview = """
		<a id="sec-overview"></a>
		<h2 id="overview">Overview</h2>
		<p>Diagram or picture illustrating a conceptual overview of the ontology.</p>
		<h3>A-Z of Terms</h3>
		<div class="azlist"> 
		<p>Classes: |
		"""
		this.od.getClasses().sort{it.getLabel()}.each {
			if (it.getLabel() != null) {
				overview += "<a href=\"#term_${it.getLabel()}\">${it.getLabel()}</a> | ";
			}
		}
		overview += """</p>
		<p>Object Properties: |
		"""
		this.od.getObjectProperties().sort{it.getLabel()}.each {
			if (it.getLabel() != null) {
				overview += "<a href=\"#term_${it.getLabel()}\">${it.getLabel()}</a> | ";
			}
		}
		overview += """</p>
		<p>Datatype Properties: |
		"""
		this.od.getDatatypeProperties().sort{it.getLabel()}.each {
			if (it.getLabel() != null) {
				overview += "<a href=\"#term_${it.getLabel()}\">${it.getLabel()}</a> | ";
			}
		}
		overview += """</p>
		<p>Individuals: |
		"""
		this.od.getIndividuals().sort{it.getLabel()}.each {
			if (it.getLabel() != null) {
				overview += "<a href=\"#term_${it.getLabel()}\">${it.getLabel()}</a> | ";
			}
		}
		
		overview += "</p>";
		
		
		return overview;
	}
	
	public String getOntClasses() {
		String ontClasses = "<h2 id=\"sec-classes\">Classes</h2>"
		this.od.getClasses().each {
			if (it.getLabel() != null) {
				ontClasses += this.getOntClass(it);
			}
		}
		return ontClasses;
	}
	
	public String getObjectProperties() {
		String rt = "<h2 id=\"sec-objectproperties\">Object Properties</h2>"
		this.od.getObjectProperties().each {
			if (it.getLabel() != null) {
				rt += this.getOntProperty(it);
			}
		}
		return rt;
	}
	
	public String getDatatypeProperties() {
		String rt = "<h2 id=\"sec-datatypeproperties\">Datatype Properties</h2>"
		this.od.getDatatypeProperties().each {
			if (it.getLabel() != null) {
				rt += this.getOntProperty(it);
			}
		}
		return rt;
	}
	
	public String getIndividuals() {
		String rt = "<h2 id=\"sec-individuals\">Individuals</h2>"
		this.od.getIndividuals().each {
			if (it.getLabel() != null) {
				rt += this.getOntIndividual(it);
			}
		}
		return rt;
	}
	
	public String getOntIndividual(Individual ind) {
		String rt = """
		<div class="specterm classterm " id="term_${ind.getLabel()}">
			<h3>Individual: ${ind.getLabel()}</h3>
			<em>${ind.getURI().toString()}</em> <br /><table style="th { float: top; }">
			<tr><th>Status:</th>
			<td><span property="vs:status" >stable</span></td></tr>
		"""
		
		rt += this.getOntIndClasses(ind);
			
		rt += """
		</table>
		<p>${ind.getComment()}</p>
		<p style="float: right; font-size: small;">[<a href="#term_${ind.getLabel()}">#</a>] <!-- ${ind.getLabel()} --> [<a href="#sec-toc">back to top</a>]</p>
		<br/>
		</div>
		"""
		return rt;
	}
	
	public String getOntProperty(OntProperty prop) {
		String rt = """
		<div class="specterm classterm " id="term_${prop.getLabel()}">
			<h3>Property: ${prop.getLabel()}</h3>
			<em>${prop.getURI().toString()}</em> <br /><table style="th { float: top; }">
			<tr><th>Status:</th>
			<td><span property="vs:status" >stable</span></td></tr>
		"""
		
		rt += this.getOntPropDomain(prop);
		rt += this.getOntPropRange(prop);
		rt += this.getOntPropInverse(prop);
		rt += this.getOntPropSub(prop);
		rt += this.getOntPropSuper(prop);
		
		rt += """
		</table>
		<p>${prop.getComment()}</p>
		<p style="float: right; font-size: small;">[<a href="#term_${prop.getLabel()}">#</a>] <!-- ${prop.getLabel()} --> [<a href="#sec-toc">back to top</a>]</p>
		<br/>
		</div>
		"""
		return rt;
	}
	
	public String getOntPropDomain(OntProperty prop) {
		String rt = "";
		int cnt = 0;
		prop.listDomain().each {
			
			if (cnt == 0) {
				rt = "<tr><th>Domain:</th> <td> ";
			}
			if (it.getLabel() != null) {
				rt += "<a href=\"#term_${it.getLabel()}\">${it.getLabel()}</a> ";
			}
			else {
				rt += "<a href=\"${it.getURI()}\">${it.getURI()}</a> ";
			}
			cnt ++;
		}
		return rt + "</td></tr> ";
	}
	
	public String getOntIndClasses(Individual ind) {
		String rt = "";
		int cnt = 0;
		ind.listOntClasses(true).each {
			if (cnt == 0) {
				rt = "<tr><th>Type of:</th> <td> ";
			}
			if (it.getLabel() != null) {
				rt += "<a href=\"#term_${it.getLabel()}\">${it.getLabel()}</a> ";
			}
			else {
				rt += "<a href=\"${it.getURI()}\">${it.getURI()}</a> ";
			}
			cnt ++;
		}
		return rt + "</td></tr> ";
	}
	
	public String getOntPropRange(OntProperty prop) {
		String rt = "";
		int cnt = 0;
		prop.listRange().each {
			if (cnt == 0) {
				rt = "<tr><th>Range:</th> <td> ";
			}
			if (it.getLabel() != null) {
				rt += "<a href=\"#term_${it.getLabel()}\">${it.getLabel()}</a> ";
			}
			else {
				rt += "<a href=\"${it.getURI()}\">${it.getURI()}</a> ";
			}
			cnt ++;
		}
		return rt + "</td></tr> ";
	}
	
	public String getOntPropInverse(OntProperty prop) {
		String rt = "";
		int cnt = 0;
		prop.listInverse().each {
			if (cnt == 0) {
				rt = "<tr><th>Inverse Properties:</th> <td> ";
			}
			if (it.getLabel() != null) {
				rt += "<a href=\"#term_${it.getLabel()}\">${it.getLabel()}</a> ";
			}
			else {
				rt += "<a href=\"${it.getURI()}\">${it.getURI()}</a> ";
			}
			cnt ++;
		}
		return rt + "</td></tr> ";
	}
	
	public String getOntPropSub(OntProperty prop) {
		String rt = "";
		int cnt = 0;
		prop.listSubProperties().each {
			if (cnt == 0) {
				rt = "<tr><th>Sub Properties:</th> <td> ";
			}
			if (it.getLabel() != null) {
				rt += "<a href=\"#term_${it.getLabel()}\">${it.getLabel()}</a> ";
			}
			else {
				rt += "<a href=\"${it.getURI()}\">${it.getURI()}</a> ";
			}
			cnt ++;
		}
		return rt + "</td></tr> ";
	}
	
	public String getOntPropSuper(OntProperty prop) {
		String rt = "";
		int cnt = 0;
		prop.listSuperProperties().each {
			if (cnt == 0) {
				rt = "<tr><th>Super Properties:</th> <td> ";
			}
			if (it.getLabel() != null) {
				rt += "<a href=\"#term_${it.getLabel()}\">${it.getLabel()}</a> ";
			}
			else {
				rt += "<a href=\"${it.getURI()}\">${it.getURI()}</a> ";
			}
			cnt ++;
		}
		return rt + "</td></tr> ";
	}
	
	public String getOntClassDeclaredProperties (OntClass clazz) {
		String rt = "";
		int cnt = 0;
		clazz.listDeclaredProperties(true).each {
			if (it != null && it.getLabel() != null) {
				if (cnt == 0) {
					rt = "<tr><th>Domain of:</th> <td> ";
				}
				if (it.getLabel() != null) {
					rt += "<a href=\"#term_${it.getLabel()}\">${it.getLabel()}</a> ";
				}
				else {
					rt += "<a href=\"${it.getURI()}\">${it.getURI()}</a> ";
				}
				cnt++;
			}
		}
		return rt + "</td></tr> ";
	}
	
	public String getOntClassSubClasses(OntClass clazz) {
		String rt = "<tr><th>Sub Classes:</th> <td> ";
		clazz.listSubClasses().each {
			if (it.getLabel() != null) {
				rt += "<a href=\"#term_${it.getLabel()}\">${it.getLabel()}</a> ";
			}
			else {
				rt += "<a href=\"${it.getURI()}\">${it.getURI()}</a> ";
			}
		}
		return rt + "</td></tr> ";
	}
	
	public String getOntClassEqualClasses(OntClass clazz) {
		String rt = "<tr><th>Equivalent Classes:</th> <td> ";
		clazz.listEquivalentClasses().each {
			if (it.getLabel() != null) {
				rt += "<a href=\"#term_${it.getLabel()}\">${it.getLabel()}</a> ";
			}
			else {
				rt += "<a href=\"${it.getURI()}\">${it.getURI()}</a> ";
			}
		}
		return rt + "</td></tr> ";
	}
	
	public String getOntClassSuperClasses(OntClass clazz) {
		String rt = "<tr><th>Super Classes:</th> <td> ";
		clazz.listSuperClasses().each {
			if (it.getLabel() != null) {
				rt += "<a href=\"#term_${it.getLabel()}\">${it.getLabel()}</a> ";
			}
			else {
				rt += "<a href=\"${it.getURI()}\">${it.getURI()}</a> ";
			}
		}
		return rt + "</td></tr> ";
	}
	
	public String getOntClassDisjointClasses(OntClass clazz) {
		String rt = "";
		int cnt = 0;
		clazz.listDisjointWith().each {
			if (cnt == 0) {
				rt = "<tr><th>Disjoint Classes:</th> <td> ";
			}
			if (it.getLabel() != null) {
				rt += "<a href=\"#term_${it.getLabel()}\">${it.getLabel()}</a> ";
			}
			else {
				rt += "<a href=\"${it.getURI()}\">${it.getURI()}</a> ";
			}
			cnt++;
		}
		return rt + "</td></tr> ";
	}
	
	public String getOntClass(OntClass clazz) {
		String classString = """
		<div class="specterm classterm " id="term_${clazz.getLabel()}"> 
            <h3>Class: ${clazz.getLabel()}</h3> 
            <em>${clazz.getURI().toString()}</em> <br /><table style="th { float: top; }"> 
		    <tr><th>Status:</th> 
		    <td><span property="vs:status" >stable</span></td></tr> 
	    """
		
		classString += this.getOntClassDeclaredProperties(clazz);
		
		if (clazz.hasSubClass()) {
			classString += this.getOntClassSubClasses(clazz);
		}
		if (clazz.hasEquivalentClass()) {
			classString += this.getOntClassEqualClasses(clazz);
		}
		if (clazz.hasSuperClass()) {
			classString += this.getOntClassSuperClasses(clazz);
		}
		
		classString += this.getOntClassDisjointClasses(clazz);
		
		classString += """
            </table> 
            <p>${clazz.getComment()}</p> 
            <p style="float: right; font-size: small;">[<a href="#term_${clazz.getLabel()}">#</a>] <!-- ${clazz.getLabel()} --> [<a href="#sec-toc">back to top</a>]</p> 
            <br/> 
            </div>
		"""
		return classString;
	}
	
	public String getExamples() {
		return """
		<a id="sec-examples"></a>
		<h2 id="examples">Examples</h2>
		<p>N3 examples of usage.</p>
		"""
	}
	
	public String getContactInformation() {
		return """
		<a id="sec-contactinformation"></a>
		<h2 id="contactinformation">Contact Information</h2>
		<p>Contact Information for questions about the ontology</p>
		"""
	}
	
	public String getFooterLicenseInformation() {
		return """
		<a id="sec-licenseinformation"></a>
		<h2 id="licenseinformation">License Information</h2>
		${this.getLicenceInformation()}
		"""
	}
	
	public String getReferences() {
		return """
		<a id="sec-references"></a>
		<h2 id="references">External References</h2>
		<p>External references for the ontology</p>
		"""
	}
	
	public String getAcknowledgements() {
		return """
		<a id="sec-acknowledgements"></a>
		<h2 id="acknowledgements">Acknowledgements</h2>
		<p>Acknowledgements references for the ontology</p>
		"""
	}
	
	public String getFooter() {
		return "</body> </html>"
	}
	
}